//g++ -g -Wall     test.cpp   -o gloox -lgloox -lgnutls -pthread

#include <iostream>
#include <time.h>
#include "../client.h"

#include "../connectiontcpclient.h"
#include "../connectionlistener.h"
#include "../messagesession.h"
#include "../messagehandler.h"
#include "../message.h"
#include "../disco.h"
#include "../rostermanager.h"
#include "../rosterlistener.h"
#include "../vcardhandler.h"
#include "../vcardmanager.h"
#include "../vcard.h"
#include "../connectiontcpclient.h"
#include "../connectionsocks5proxy.h"
#include "../connectionhttpproxy.h"
using namespace std;
using namespace gloox;

#define USERNAME	"anne.antingting@gmail.com"
#define PASSWORD	"antingting"
//#define USERNAME	"0@gmail"
//#define PASSWORD	"0123"			@chat.facebook.com
#define USERNAME_FB	"-1323332393@chat.facebook.com"
#define  KEY		"bf83eabf819c1e6163d9ec38d9e9ae11|8baa761aa8bc573af60d4675-1323332393|055ae45fdee88045009523122c2ea62d"
#define PASSWORD_FB	"055ae45fdee88045009523122c2ea62d"
#define  TEST_FB	"chenxixm@chat.facebook.com"

class Bot : public gloox::ConnectionListener, gloox::MessageHandler, gloox::RosterListener, VCardHandler
{
public:
	Bot(const char* username, const char* password) : client_(gloox::JID(username), password)
	{
		
		//client_.setServer("talk.google.com");
		//client_.setPort(5222);
		//client_.setUsername(USERNAME);
		client_.setJID(USERNAME_FB);
		client_.setServer("chat.facebook.com");
		//client_.setJID(TEST_FB);
		//client_.setServer("chat.facebook.com");
		client_.setPassword(PASSWORD_FB);
		client_.setResource("gloox2008");
		client_.setPresence();
		client_.setTls( TLSDisabled );
		client_.registerConnectionListener(this);
		client_.registerMessageHandler(this);
		client_.rosterManager()->registerRosterListener(this);//, false);
		m_vManager = new VCardManager( &client_ );
		client_.setSASLMechanisms( SaslMechFacebook );
		client_.setAuthcid( KEY );

		//ConnectionTCPClient* conn0 = new ConnectionTCPClient( client_.logInstance(), "proxy.tencent.com", 8080 );
		//ConnectionHTTPProxy* conn1 = new ConnectionHTTPProxy( &client_, conn0, client_.logInstance(), "talk.google.com", 5222 );
		ConnectionTCPClient* conn0 = new ConnectionTCPClient( client_.logInstance(), "172.19.69.36", 8080 );
		ConnectionHTTPProxy* conn1 = new ConnectionHTTPProxy( &client_, conn0, client_.logInstance(), "chat.facebook.com", 5222 );
		//conn1->setProxyAuth( "xichen", "xichen" );
		client_.setConnectionImpl( conn1 );

		if( client_.connect( false ) )
	    {	
			ConnectionError ce = ConnNoError;

			while( ce == ConnNoError )
			{
			  ce = client_.recv(1000);
			}
			printf( "ce: %d\n", ce );
			
			//fd = static_cast<ConnectionTCPClient*>( client_.connectionImpl() )->socket();
	    }
		else
		{
			fd = -1;
			printf( "fd error\n" );
		}
			
	}

	virtual void onConnect()
	{
		cout << "Connected." << endl;
		client_.setPresence(Presence::Available, 31);
	}

	virtual void handleMessage(const gloox::Message& stanza, gloox::MessageSession* session = 0)
	{
		cout << "Handle message." << endl;
		if(stanza.body() == "")
			return;
		cout << stanza.from().full().c_str() << " , " << stanza.body() << endl;
		JID jid(stanza.from().bare());
		MessageSession* s = new MessageSession( &client_,jid);

		s->send(stanza.body());
		client_.disposeMessageSession( s );
	}

	virtual void handleRoster(const gloox::Roster& roster)
	{
		cout << "Roster." << endl;
		gloox::Roster::const_iterator it = roster.begin();
		for (; it != roster.end(); ++it)
		{
			const gloox::RosterItem* item = (*it).second;
			cout << "Friend: " << item->jid() << endl;
		}
	}
	virtual void handleItemAdded( const JID& jid )
	{
		cout << "handleItemAdded." << endl;
	}
	virtual void handleItemSubscribed( const JID& /*jid*/ )
	{
		cout << "handleItemSubscribed." << endl;
	}
	virtual void handleItemRemoved( const JID& jid )
	{
		cout << "handleItemRemoved." << endl;
	}
	virtual void handleItemUpdated( const JID& jid )
	{
		cout << "handleItemUpdated." << endl;
	}
	virtual void handleItemUnsubscribed( const JID& /*jid*/ )
	{
		cout << "handleItemUnsubscribed." << endl;
	}

	virtual void handleRosterPresence( const RosterItem& item, const std::string& resource,
					   Presence::PresenceType presence, const std::string& msg ) 
	{
		cout << "handleRosterPresence." << endl;
		if( presence < Presence::Unavailable)	
		{
			cout << "Online: " << item.jid() << " res:  " << resource << endl;
			m_vManager->fetchVCard( item.jid(), this);
		}else	//offline
		{
			cout << "Offline: " << item.jid() << endl;
		}	
		
	}
	virtual void handleSelfPresence( const RosterItem& item, const std::string& /*resource*/,
					 Presence::PresenceType /*presence*/, const std::string& /*msg*/ ) 
{
	cout << "handleSelfPresence:" << item.jid() << endl;
}

	virtual bool handleSubscriptionRequest( const JID& /*jid*/, const std::string& /*msg*/ )
	{
		cout << "handleSubscriptionRequest." << endl;
		return true;
	}
	virtual bool handleUnsubscriptionRequest( const JID& /*jid*/, const std::string& /*msg*/ )
	{
		cout << "handleUnsubscriptionRequest." << endl;
		return true;
	}
	virtual void handleNonrosterPresence( const Presence& presence ) {cout << presence.from().bare() << ":" << presence.presence() << "+" << presence.status() << endl;   m_vManager->fetchVCard( presence.from().bare(), this);}
	virtual void handleRosterError( const IQ& /*iq*/ ) { cout <<"!" << endl;}

	virtual void onDisconnect(gloox::ConnectionError reason)
	{
		cout << "Disconnected. reason: " << reason << endl;
		if( reason == ConnAuthenticationFailed )
		      cout << "auth failed" << endl;
		exit(0);
	}
	virtual bool onTLSConnect(const gloox::CertInfo &info)
	{
		return true;
	}

    virtual void handleVCardResult( VCardContext context, const JID& jid,
                                    StanzaError se = StanzaErrorUndefined  )
    {
      printf( "vcard result: context: %d, jid: %s, error: %d\n", context, jid.full().c_str(), se );
//    m_vManager->fetchVCard( jid, this );
    }

    virtual void handleVCard( const JID& jid, const VCard *v )
    {
      if( !v )
      {
        printf( "empty vcard!\n" );
        return;
      }

//     VCard* vcard = new VCard( *v );
//      printf( "received vcard for %s: %s\n", jid.full().c_str(), vcard->tag()->xml().c_str() );
      printf( "online %s: %s\n", jid.full().c_str(), v->formattedname().c_str() );
//	delete vcard;
    }

   ConnectionError recv(int timeout)
   {
	return client_.recv(timeout);
   }

	int fd;
	Client client_;
private:
	VCardManager *m_vManager;
	
};

//int main()
//{
//	//Bot* bot  = new Bot("xichen", "xichen");
//	Bot* bot  = new Bot("", "");
//	fd_set socks;
//
//	delete bot;
//}

